package knapsackga;

import java.io.FileWriter;
import java.util.Arrays;
import java.util.Comparator;

public class KnapsackMain {
	public static void main(String[] args) throws Exception {
		String data_dir = "src/data/";
		String[] definition_files = { "sample-32items.dat", "sample-128items.dat", };

		int num_runs = 30;
		int population_size = 1000;
		int num_generations = 100;

		// For each knapsack we will do num_runs
		for (String definition_file : definition_files) {
			data_dir = "src/data/";
			System.out.println("Using definition file: " + definition_file);
			Knapsack knapsack = new Knapsack(data_dir + definition_file);
			FitnessFunction fitness_func = new FitnessFunctionA(knapsack);

			// hold the data from all the runs
			Double[][][] data = new Double[num_runs][][];

			// do the runs storing the data
			System.out.print("Progress ");
			for (int run = 0; run < num_runs; run++) {
				System.out.print(run + " ");
				KnapsackGA ga = new KnapsackGA(knapsack, fitness_func);
				data[run] = ga.start(population_size, num_generations);
			}
			System.out.println("\n");

			// write the data from each run to files
			data_dir = "src/data/tourny/";
			for (int run = 0; run < num_runs; run++) {
				FileWriter f = new FileWriter(data_dir + definition_file
						+ "run" + run + ".txt");

				for (int gen = 0; gen < num_generations; gen++) {
					f.write(Integer.toString(gen));
					f.write("\t");
					Arrays.sort(data[run][gen], new SortDescending());
					for (int indv = 0; indv < population_size; indv++) {
						f.write(Double.toString(data[run][gen][indv]));
						f.write("\t");
					}
					f.write("\n");
				}

				f.close();
			}

			// average the solutions over each run in each generation
			Double[] average_fitness = new Double[num_generations];
			Double[] best_fitness = new Double[num_generations];

			FileWriter f = new FileWriter(data_dir + definition_file
					+ "average.txt");

			for (int gen = 0; gen < num_generations; gen++) {
				average_fitness[gen] = new Double(0);
				best_fitness[gen] = new Double(Double.NEGATIVE_INFINITY);

				f.write(Integer.toString(gen));
				f.write("\t");

				for (int run = 0; run < num_runs; run++) {
					for (int indv = 0; indv < population_size; indv++) {
						average_fitness[gen] += data[run][gen][indv];
						best_fitness[gen] = Math.max(best_fitness[gen],
								data[run][gen][indv]);
					}
				}
				average_fitness[gen] /= (num_runs * population_size);
				f.write(Double.toString(best_fitness[gen]));
				f.write("\t");
				f.write(Double.toString(average_fitness[gen]));
				f.write("\n");
			}
			f.close();
		}
	}

	public static class SortDescending implements Comparator<Double> {

		@Override
		public int compare(Double o1, Double o2) {
			return (int) Math.signum(o2 - o1);
		}

	}
}
